home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Joystick Magazine 1996 April
/
Joystick.Hors serie avril 96Flashback+demos.iso
/
wing
/
halftone.c_
/
halftone.c
Wrap
Text File
|
1994-12-08
|
22KB
|
575 lines
/**************************************************************************
HALFTONE.C - A halftoning demo for WinG
**************************************************************************/
/**************************************************************************
(C) Copyright 1994 Microsoft Corp. All rights reserved.
You have a royalty-free right to use, modify, reproduce and
distribute the Sample Files (and/or any modified version) in
any way you find useful, provided that you agree that
Microsoft has no warranty obligations or liability for any
Sample Application Files which are modified.
**************************************************************************/
#include <windows.h>
#include <windowsx.h>
#include <commdlg.h>
#include <wing.h>
#include "halftone.h"
#include "..\utils\utils.h"
/*----------------------------------------------------------------------------*\
| |
| g l o b a l v a r i a b l e s |
| |
\*----------------------------------------------------------------------------*/
static char szAppName[]="WinG Halftoning Sample";
static char szAppFilter[]="Bitmaps\0*.bmp;*.dib\0";
static HINSTANCE hInstApp;
static HWND hwndApp;
static HPALETTE hpalApp;
static BOOL fAppActive;
static BOOL fCustomDither = TRUE;
static PDIB pdibOriginal = 0;
static PDIB pdibHalftone = 0;
#ifdef WIN32
#define _export
#endif
/*----------------------------------------------------------------------------*\
| |
| f u n c t i o n d e f i n i t i o n s |
| |
\*----------------------------------------------------------------------------*/
LONG FAR PASCAL _export AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
LONG AppCommand (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
void AppExit(void);
BOOL AppIdle(void);
void AppOpenFile(HWND hwnd, LPSTR szFileName);
PDIB DibHalftoneDIB( PDIB pSource );
/*----------------------------------------------------------------------------*\
| AppAbout( hDlg, uiMessage, wParam, lParam ) |
| |
| Description: |
| This function handles messages belonging to the "About" dialog box. |
| The only message that it looks for is WM_COMMAND, indicating the use |
| has pressed the "OK" button. When this happens, it takes down |
| the dialog box. |
| |
| Arguments: |
| hDlg window handle of about dialog window |
| uiMessage message number |
| wParam message-dependent |
| lParam message-dependent |
| |
| Returns: |
| TRUE if message has been processed, else FALSE |
| |
\*----------------------------------------------------------------------------*/
BOOL FAR PASCAL _export AppAbout(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch (msg)
{
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
EndDialog(hwnd,TRUE);
}
break;
case WM_INITDIALOG:
return TRUE;
}
return FALSE;
}
/*----------------------------------------------------------------------------*\
| AppInit( hInst, hPrev) |
| |
| Description: |
| This is called when the application is first loaded into |
| memory. It performs all initialization that doesn't need to be done |
| once per instance. |
| |
| Arguments: |
| hInstance instance handle of current instance |
| hPrev instance handle of previous instance |
| |
| Returns: |
| TRUE if successful, FALSE if not |
| |
\*----------------------------------------------------------------------------*/
BOOL AppInit(HINSTANCE hInst,HINSTANCE hPrev,int sw,LPSTR szCmdLine)
{
WNDCLASS cls;
int dx,dy;
HMENU hMenu;
/* Save instance handle for DialogBoxes */
hInstApp = hInst;
// Clear the System Palette so that WinG blting runs at full speed.
ClearSystemPalette();
if (!hPrev)
{
/*
* Register a class for the main application window
*/
cls.hCursor = LoadCursor(NULL,IDC_ARROW);
cls.hIcon = LoadIcon(hInst,"AppIcon");
cls.lpszMenuName = "AppMenu";
cls.lpszClassName = szAppName;
cls.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
cls.hInstance = hInst;
cls.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
cls.lpfnWndProc = (WNDPROC)AppWndProc;
cls.cbWndExtra = 0;
cls.cbClsExtra = 0;
if (!RegisterClass(&cls))
return FALSE;
}
dx = GetSystemMetrics (SM_CXSCREEN) / 2;
dy = GetSystemMetrics (SM_CYSCREEN) / 2;
hpalApp = WinGCreateHalftonePalette();
hwndApp = CreateWindow (szAppName, // Class name
szAppName, // Caption
WS_OVERLAPPEDWINDOW, // Style bits
CW_USEDEFAULT, 0, // Position
dx,dy, // Size
(HWND)NULL, // Parent window (no parent)
(HMENU)NULL, // use class menu
hInst, // handle to window instance
(LPSTR)NULL // no params to pass on
);
ShowWindow(hwndApp,sw);
//*** Check the default dither selection
hMenu = GetMenu(hwndApp);
CheckMenuItem(hMenu, MENU_WING, fCustomDither ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hMenu, MENU_GDI, fCustomDither ? MF_UNCHECKED : MF_CHECKED);
if (*szCmdLine)
AppOpenFile(hwndApp, szCmdLine);
return TRUE;
}
/*----------------------------------------------------------------------------*\
| AppExit() |
| |
| Description: |
| App is just about to exit, cleanup. |
| |
\*----------------------------------------------------------------------------*/
void AppExit()
{
if (hpalApp)
DeleteObject(hpalApp);
if (pdibOriginal)
DibFree(pdibOriginal);
if (pdibHalftone)
DibFree(pdibHalftone);
}
/*----------------------------------------------------------------------------*\
| WinMain( hInst, hPrev, lpszCmdLine, cmdShow ) |
| |
| Description: |
| The main procedure for the App. After initializing, it just goes |
| into a message-processing loop until it gets a WM_QUIT message |
| (meaning the app was closed). |
| |
| Arguments: |
| hInst instance handle of this instance of the app |
| hPrev instance handle of previous instance, NULL if first |
| szCmdLine ->null-terminated command line |
| cmdShow specifies how the window is initially displayed |
| |
| Returns: |
| The exit code as specified in the WM_QUIT message. |
| |
\*----------------------------------------------------------------------------*/
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
{
MSG msg;
/* Call initialization procedure */
if (!AppInit(hInst,hPrev,sw,szCmdLine))
return FALSE;
/*
* Polling messages from event queue
*/
for (;;)
{
if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
if (AppIdle())
WaitMessage();
}
}
AppExit();
return msg.wParam;
}
/*----------------------------------------------------------------------------*\
| AppIdle() |
| |
| Description: |
| Place to do idle time stuff. |
| |
\*----------------------------------------------------------------------------*/
BOOL AppIdle()
{
if (fAppActive)
{
//
// we are the foreground app.
//
return TRUE; // nothing to do.
}
else
{
//
// we are a background app.
//
return TRUE; // nothing to do.
}
}
/*----------------------------------------------------------------------------*\
| AppOpenFile() |
| |
| Description: |
| Open a file. |
| |
\*----------------------------------------------------------------------------*/
void AppOpenFile(HWND hwnd, LPSTR szFileName)
{
HCURSOR hCur = LoadCursor(NULL, IDC_WAIT);
PDIB pdibNew;
hCur = SetCursor(hCur);
pdibNew = DibOpenFile(szFileName);
if (pdibNew)
{
if (pdibOriginal)
DibFree(pdibOriginal);
if (pdibHalftone)
DibFree(pdibHalftone);
pdibOriginal = pdibNew;
pdibHalftone = DibHalftoneDIB(pdibOriginal);
if (DibBitCount(pdibOriginal) != 24)
{
MessageBox(hwnd, "Not a 24-bit DIB!", "Oops", MB_OK);
}
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
hCur = SetCursor(hCur);
}
/*----------------------------------------------------------------------------*\
| AppPaint(hwnd, hdc) |
| |
| Description: |
| The paint function. |
| |
| Arguments: |
| hwnd window painting into |
| hdc display context to paint to |
| |
\*----------------------------------------------------------------------------*/
AppPaint (HWND hwnd, HDC hdc)
{
if (fCustomDither && pdibHalftone)
{
StretchDIBits(hdc,
0, 0, DibWidth(pdibHalftone), DibHeight(pdibHalftone),
0, 0, DibWidth(pdibHalftone), DibHeight(pdibHalftone),
DibPtr(pdibHalftone), DibInfo(pdibHalftone),
DIB_RGB_COLORS, SRCCOPY);
}
else if (pdibOriginal)
{
StretchDIBits(hdc,
0, 0, DibWidth(pdibOriginal), DibHeight(pdibOriginal),
0, 0, DibWidth(pdibOriginal), DibHeight(pdibOriginal),
DibPtr(pdibOriginal), DibInfo(pdibOriginal),
DIB_RGB_COLORS, SRCCOPY);
}
return TRUE;
}
/*----------------------------------------------------------------------------*\
| AppWndProc( hwnd, uiMessage, wParam, lParam ) |
| |
| Description: |
| The window proc for the app's main (tiled) window. This processes all |
| of the parent window's messages. |
| |
\*----------------------------------------------------------------------------*/
LONG FAR PASCAL _export AppWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
BOOL f;
switch (msg)
{
case WM_CREATE:
break;
case WM_ACTIVATEAPP:
fAppActive = (BOOL)wParam;
break;
case WM_TIMER:
break;
case WM_ERASEBKGND:
break;
case WM_INITMENU:
break;
case WM_COMMAND:
return AppCommand(hwnd,msg,wParam,lParam);
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CLOSE:
break;
case WM_PALETTECHANGED:
if ((HWND)wParam == hwnd)
break;
// fall through to WM_QUERYNEWPALETTE
case WM_QUERYNEWPALETTE:
hdc = GetDC(hwnd);
if (hpalApp)
SelectPalette(hdc, hpalApp, FALSE);
f = RealizePalette(hdc);
ReleaseDC(hwnd,hdc);
if (f)
InvalidateRect(hwnd,NULL,TRUE);
return f;
case WM_PAINT:
hdc = BeginPaint(hwnd,&ps);
if (hpalApp)
{
SelectPalette(hdc, hpalApp, FALSE);
RealizePalette(hdc);
}
AppPaint (hwnd,hdc);
EndPaint(hwnd,&ps);
return 0L;
}
return DefWindowProc(hwnd,msg,wParam,lParam);
}
/*----------------------------------------------------------------------------*\
| AppCommand(hwnd, msg, wParam, lParam ) |
| |
| Description: |
| Handles WM_COMMAND messages for the main window (hwndApp) |
| of the parent window's messages. |
| |
\*----------------------------------------------------------------------------*/
LONG AppCommand (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
char achFileName[128];
OPENFILENAME ofn;
switch(wParam)
{
case MENU_ABOUT:
DialogBox(hInstApp,"AppAbout",hwnd,(DLGPROC)AppAbout);
break;
case MENU_OPEN:
achFileName[0] = 0;
/* prompt user for file to open */
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwnd;
ofn.hInstance = NULL;
ofn.lpstrFilter = szAppFilter;
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 0;
ofn.lpstrFile = achFileName;
ofn.nMaxFile = sizeof(achFileName);
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = NULL;
ofn.lCustData = 0;
ofn.lpfnHook = NULL;
ofn.lpTemplateName = NULL;
if (GetOpenFileName(&ofn))
{
AppOpenFile(hwnd,achFileName);
}
break;
case MENU_EXIT:
PostMessage(hwnd,WM_CLOSE,0,0L);
break;
case MENU_WING:
case MENU_GDI:
{
HMENU hMenu;
fCustomDither = (wParam == MENU_WING);
hMenu = GetMenu(hwnd);
CheckMenuItem(hMenu, MENU_WING,
fCustomDither ? MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hMenu, MENU_GDI,
fCustomDither ? MF_UNCHECKED : MF_CHECKED);
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
}
break;
}
return 0L;
}
/***************************************************************************
DibHalftoneDIB
Halftone a 24-bit DIB to the 8-bit WinG Halftone Palette
*/
//*** These tables are defined in httables.c
extern char unsigned aDividedBy51Rounded[256];
extern char unsigned aDividedBy51[256];
extern char unsigned aModulo51[256];
extern char unsigned aTimes6[6];
extern char unsigned aTimes36[6];
extern char unsigned aHalftone8x8[64];
extern char unsigned aWinGHalftoneTranslation[216];
PDIB DibHalftoneDIB( PDIB pSource )
{
//*** Create an 8-bit DIB to halftone to
PDIB pDestination = DibCreate(8,DibWidth(pSource),DibHeight(pSource));
//*** Only work on 24-bit sources
if(pDestination && hpalApp && (DibBitCount(pSource) == 24))
{
long PixelsPerScanline = DibWidth(pSource);
int Scanline;
//*** Fill in the DIB color table with the halftone palette
DibSetUsage(pDestination, hpalApp, DIB_RGB_COLORS);
//*** Step through, converting each pixel in each scan line
//*** to the nearest halftone match
for(Scanline = 0;Scanline < (int)DibHeight(pSource);Scanline++)
{
char unsigned _huge *pSourceScanline =
(char unsigned _huge *)DibXY(pSource,0,Scanline);
char unsigned _huge *pDestinationScanline =
(char unsigned _huge *)DibXY(pDestination,0,Scanline);
int Pixel;
for(Pixel = 0;Pixel < (int)DibWidth(pSource);Pixel++)
{
//*** This is the meat of the halftoning algorithm:
//*** Convert an RGB into an index into the halftone palette.
//*** First, extract the raw RGB information
int Red = pSourceScanline[Pixel*3 + 2];
int Green = pSourceScanline[Pixel*3 + 1];
int Blue = pSourceScanline[Pixel*3];
//*** Now, look up each value in the halftone matrix
//*** using an 8x8 ordered dither.
char unsigned RedTemp = aDividedBy51[Red]
+ (aModulo51[Red] > aHalftone8x8[(Pixel%8)*8
+ Scanline%8]);
char unsigned GreenTemp = aDividedBy51[(char unsigned)Green]
+ (aModulo51[Green] > aHalftone8x8[
(Pixel%8)*8 + Scanline%8]);
char unsigned BlueTemp = aDividedBy51[(char unsigned)Blue]
+ (aModulo51[Blue] > aHalftone8x8[
(Pixel%8)*8 +Scanline%8]);
//*** Recombine the halftoned RGB values into a palette index
char unsigned PaletteIndex =
RedTemp + aTimes6[GreenTemp] + aTimes36[BlueTemp];
//*** And translate through the WinG Halftone Palette
//*** translation vector to give the correct value.
pDestinationScanline[Pixel] = aWinGHalftoneTranslation[PaletteIndex];
}
}
}
else
{
//*** Punt on anything but 24bpp
DibFree(pDestination);
pDestination = 0;
}
return pDestination;
}